import math
import os
import neat
from src.python.GA_NN_Neat import visualize
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_absolute_percentage_error, adjusted_rand_score

# 评价函数
from src.python.util.getResoures import getData


def eval_genomes(genomes, config):
    for genome_id, genome in genomes:  # for each individual
        genome.fitness = 1000000  # 4 xor evaluations
        net = neat.nn.FeedForwardNetwork.create(genome, config)  # 每一个基因都生成一个神经网络
        for xi, xo in zip(xor_inputs, xor_outputs):
            output = net.activate(xi)
            # genome.fitness -= math.fabs((output[0] - xo[0]))
            # genome.fitness -= (math.fabs((output[1] - xo[1]))*100)
            genome.fitness -= (output[0] - xo[0])**2
            cha = output[1] - xo[1]
            genome.fitness -= cha ** 2


def solve(config_file):
    # Load configuration.
    config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction,
                         neat.DefaultSpeciesSet, neat.DefaultStagnation,
                         config_file)
    # 根据config产生初始种群
    p = neat.Population(config)

    # Add a stdout reporter to show progress in the terminal.
    p.add_reporter(neat.StdOutReporter(True))
    stats = neat.StatisticsReporter()
    p.add_reporter(stats)
    # 每隔50次迭代输出一次日志文件
    p.add_reporter(neat.Checkpointer(500))

    # eval_genomes:评价函数  300：迭代数
    winner = p.run(eval_genomes, 500)

    # Display the winning genome.
    print('\nBest genome:\n{!s}'.format(winner))

    # Show output of the most fit genome against training data.
    print('\nOutput:')
    winner_net = neat.nn.FeedForwardNetwork.create(winner, config)
    # 验证
    y_pre = []
    for i in range(len(y_test)):
        output = winner_net.activate(x_tuple_test[i])
        y_pre.append(list(output))
    # 评估分数
    mae = mean_absolute_error(y_pred=y_pre, y_true=y_test)
    print("平均绝对误差MAE:", mae)
    mse = mean_squared_error(y_pred=y_pre, y_true=y_test)
    print("均方根误差RMSE:", math.sqrt(mse))
    print("均方误差MSE:", mse)
    mape = mean_absolute_percentage_error(y_pred=y_pre, y_true=y_test)
    print("平均绝对百分比误差MAPE:", mape)
    # 保存模型
    # winner.save('D:\python-3.8.2\Sofia_Holike_Blanking_Forecast\src\python\GA_NN_Neat\model\My_Neat_Model.h5')
    # 结果可视化 ----------------------------------------------------------------
    # node_names = {-1: 'A', -2: 'B', 0: 'A XOR B'}
    if(b):
        visualize.draw_net(config, winner, True)
        visualize.plot_stats(stats, ylog=False, view=True)
        visualize.plot_species(stats, view=True)

        p = neat.Checkpointer.restore_checkpoint('neat-checkpoint-49')
        p.run(eval_genomes, 10)

def run():
    print("------------------------------------------- Neat遗传神经网络回归预测模型：-------------------------------------------")
    global b,x_train, x_test, y_train, y_test,xor_outputs,x_tuple_test,xor_inputs

    b = True
    # 获取数据
    x_train, x_test, y_train, y_test = getData()

    xor_inputs = []
    for i in range(x_train.shape[0]):
        temp = []
        column = x_train.columns
        for j in range(len(column)):
            temp.append(x_train.iloc[i][column[j]])
        xor_inputs.append(tuple(temp))

    xor_outputs = []
    for i in range(y_train.shape[0]):
        temp = [y_train.iloc[i]['长度'], y_train.iloc[i]['板材利用率']]
        xor_outputs.append(tuple(temp))

    x_tuple_test = []
    for i in range(x_test.shape[0]):
        temp = []
        column = x_test.columns
        for j in range(len(column)):
            temp.append(x_test.iloc[i][column[j]])
        x_tuple_test.append(tuple(temp))

    local_dir = os.path.dirname(__file__)
    config_path = os.path.join(local_dir, 'config-feedforward')
    solve(config_path)


if __name__ == '__main__':
    run()
